home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / dev / src / stefanb_src.lha / Old_Projects / ToolManager / Source / library / dockobj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-13  |  43.6 KB  |  1,386 lines

  1. /*
  2.  * dockobj.c  V2.1.01
  3.  *
  4.  * TMObject, Type: Dock
  5.  *
  6.  * (c) 1990-1995 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerLib.h"
  10.  
  11. /* node for one tool */
  12. struct DockTool {
  13.                  struct DockTool    *dt_Next;
  14.                  char               *dt_ExecName;
  15.                  struct TMLink      *dt_ExecLink;
  16.                  struct TMLinkImage *dt_ImageLink;
  17.                  struct TMLink      *dt_SoundLink;
  18.                 };
  19.  
  20. /* extended TMObject structure for TMOBJTYPE_Dock objects */
  21. struct TMObjectDock {
  22.                      struct TMObject  do_Object;
  23.                      ULONG            do_Flags;
  24.                      ULONG            do_Columns;
  25.                      struct TextAttr *do_Font;   /* User supplied font */
  26.                      char            *do_HotKey;
  27.                      ULONG            do_LeftEdge;
  28.                      char            *do_PubScreen;
  29.                      char            *do_Title;
  30.                      struct DockTool *do_Tools;
  31.                      ULONG            do_TopEdge;
  32.                      CxObj           *do_CxObj;
  33.                      struct TMLink    do_Link;
  34.                      UWORD            do_Left;   /* Drawing start position */
  35.                      UWORD            do_Top;
  36.                      UWORD            do_Width;  /* Inner Window Width/Height */
  37.                      UWORD            do_Height;
  38.                      UWORD            do_XSize;  /* Image/Gadget box size */
  39.                      UWORD            do_YSize;
  40.                      struct Window   *do_Window;
  41.                      void            *do_AppWindow;
  42.                      struct Gadget    do_DragGadget;
  43.                      UWORD            do_FillPen;
  44.                      UWORD            do_BackPen;
  45.                      struct TextAttr  do_TextAttr;   /* Font for gadgets */
  46.                      struct TextFont *do_TextFont;   /* Screen font (open) */
  47.                      struct TextFont *do_GadgetFont; /* Gadget font (open) */
  48.                      void            *do_VisualInfo;
  49.                      struct Menu     *do_Menu;
  50.                      struct Gadget   *do_GadToolsGadgets;
  51.                      struct DockTool *do_Selected;
  52.                      UWORD            do_SelectX;
  53.                      UWORD            do_SelectY;
  54.                      ULONG            do_Seconds;
  55.                      ULONG            do_Micros;
  56.                      BOOL             do_DeferClose;
  57.                      BOOL             do_ReOpen;
  58.                     };
  59.  
  60. /* do_Flags */
  61. #define DO_Activated (1L<<0)
  62. #define DO_Centered  (1L<<1)
  63. #define DO_FrontMost (1L<<2)
  64. #define DO_Menu      (1L<<3)
  65. #define DO_Pattern   (1L<<4)
  66. #define DO_PopUp     (1L<<5)
  67. #define DO_Text      (1L<<6)
  68. #define DO_Vertical  (1L<<7)
  69. #define DO_Backdrop  (1L<<8)
  70. #define DO_Sticky    (1L<<9)
  71.  
  72. /* Tag to Flag mapping table for PackBoolTags */
  73. static struct TagItem flagmap[]={
  74.                                  TMOP_Activated, DO_Activated,
  75.                                  TMOP_Centered,  DO_Centered,
  76.                                  TMOP_FrontMost, DO_FrontMost,
  77.                                  TMOP_Menu,      DO_Menu,
  78.                                  TMOP_Pattern,   DO_Pattern,
  79.                                  TMOP_PopUp,     DO_PopUp,
  80.                                  TMOP_Text,      DO_Text,
  81.                                  TMOP_Vertical,  DO_Vertical,
  82.                                  TMOP_Backdrop,  DO_Backdrop,
  83.                                  TMOP_Sticky,    DO_Sticky,
  84.                                  TAG_DONE};
  85.  
  86. /* Library bases */
  87. struct Library *DiskfontBase;
  88.  
  89. /* Close a window safely */
  90. static void SafeCloseWindow(struct Window *w)
  91. {
  92.  struct IntuiMessage *msg;
  93.  
  94.  DEBUG_PRINTF("SafeCloseWindow: 0x%08lx\n",w);
  95.  
  96.  /* we forbid here to keep out of race conditions with Intuition */
  97.  Forbid();
  98.  
  99.  /* Remove all messsages for this window */
  100.  msg=GetHead(&w->UserPort->mp_MsgList);
  101.  while (msg)
  102.   /* Does this message point to the window? */
  103.   if (msg->IDCMPWindow==w) {
  104.    struct IntuiMessage *nextmsg=GetSucc(msg);
  105.  
  106.    /* Yes. Remove it from port */
  107.    Remove((struct Node *) msg);
  108.  
  109.    /* Reply it */
  110.    ReplyMsg((struct Message *) msg);
  111.  
  112.    /* Get pointer to next message */
  113.    msg=nextmsg;
  114.   }
  115.    /* No. Get pointer to next message */
  116.   else msg=GetSucc(msg);
  117.  
  118.  /* clear UserPort so Intuition will not free it */
  119.  w->UserPort=NULL;
  120.  
  121.  /* tell Intuition to stop sending more messages */
  122.  ModifyIDCMP(w,0);
  123.  
  124.  /* turn multitasking back on */
  125.  Permit();
  126.  
  127.  DEBUG_PRINTF("Closing window\n");
  128.  
  129.  /* and really close the window */
  130.  CloseWindow(w);
  131.  
  132.  DEBUG_PRINTF("Window closed\n");
  133. }
  134.  
  135. /* Pattern */
  136. static UWORD BackgroundPattern[]={0xaaaa,0x5555};
  137.  
  138. /* Open Dock Window */
  139. static void OpenDockWindow(struct TMObjectDock *tmobj, BOOL beep)
  140. {
  141.  struct Screen *pubsc;
  142.  
  143.  /* Open on frontmost public screen? */
  144.  if (tmobj->do_Flags & DO_FrontMost) {
  145.   ULONG lock;
  146.  
  147.   /* Avoid race conditions */
  148.   Forbid();
  149.  
  150.   /* Lock IntuitionBase */
  151.   lock=LockIBase(0);
  152.  
  153.   /* Get active screen */
  154.   pubsc=IntuitionBase->ActiveScreen;
  155.   if (pubsc) {
  156.    ULONG type=pubsc->Flags & SCREENTYPE;
  157.  
  158.    DEBUG_PRINTF("Screen flags: 0x%08lx",pubsc->Flags);
  159.    DEBUG_PRINTF(" Screen type: 0x%08lx\n",type);
  160.  
  161.    /* Found a public screen? */
  162.    if (!((type==WBENCHSCREEN) || (type==PUBLICSCREEN)))
  163.     /* No! */
  164.     pubsc=NULL;
  165.   }
  166.  
  167.   /* Unlock IntuitionBase */
  168.   UnlockIBase(lock);
  169.  
  170.   /* Lock public screen */
  171.   if (pubsc) {
  172.    struct List *pubsclist;
  173.  
  174.    /* Get a pointer to the public screen list */
  175.    if (pubsclist=LockPubScreenList()) {
  176.     struct PubScreenNode *pubscnode=GetHead(pubsclist);
  177.     UBYTE namebuf[MAXPUBSCREENNAME+1];
  178.  
  179.     /* Scan list */
  180.     while (pubscnode) {
  181.      /* Does this node point to our screen? */
  182.      if (pubscnode->psn_Screen==pubsc) {
  183.       /* Yes. Copy screen name */
  184.       strcpy(namebuf,pubscnode->psn_Node.ln_Name);
  185.       break;
  186.      }
  187.  
  188.      /* get a pointer to next node */
  189.      pubscnode=GetSucc(pubscnode);
  190.     }
  191.  
  192.     /* Release public screen list */
  193.     UnlockPubScreenList();
  194.  
  195.     /* Lock screen */
  196.     if (pubscnode)
  197.      pubsc=LockPubScreen(namebuf);
  198.     else
  199.      pubsc=NULL;
  200.    }
  201.    else pubsc=NULL; /* No public screens??? */
  202.   }
  203.  
  204.   /* OK, we have a screen now */
  205.   Permit();
  206.  } else
  207.   /* Lock public screen */
  208.   pubsc=LockPubScreen(tmobj->do_PubScreen);
  209.  
  210.  DEBUG_PRINTF("PubScreen: 0x%08lx\n",pubsc);
  211.  
  212.  /* Got a locked public screen? */
  213.  if (pubsc) {
  214.   struct DrawInfo *dri;
  215.  
  216.   /* Get screen draw info */
  217.   if (dri=GetScreenDrawInfo(pubsc)) {
  218.    void *vi;
  219.  
  220.    /* Get screen visual info */
  221.    if (vi=GetVisualInfo(pubsc,TAG_DONE)) {
  222.     struct TextFont *tf;
  223.  
  224.     /* Open screen font */
  225.     if (tf=OpenFont(pubsc->Font)) {
  226.      struct Window *w;
  227.      struct DockTool *dt=tmobj->do_Tools;
  228.      struct TextFont *gadfont=NULL;
  229.      UWORD wx=0,wy=0;
  230.      BOOL borderless=tmobj->do_Title==NULL;
  231.      BOOL text=(tmobj->do_Flags & DO_Text)!=0;
  232.  
  233.      /* Got ANY tools??? */
  234.      if (dt) {
  235.       /* Calculate box sizes */
  236.       ULONG maxx=0,maxy=0,count=0;
  237.       ULONG fheight;
  238.       struct RastPort tmprp;
  239.  
  240.       /* Init RastPort for text writing */
  241.       InitRastPort(&tmprp);
  242.  
  243.       /* Set default font */
  244.       SetFont(&tmprp,tf);
  245.       fheight=tf->tf_YSize+INTERHEIGHT+1;
  246.  
  247.       /* User specified font? */
  248.       if (tmobj->do_Font &&
  249.           (DiskfontBase=OpenLibrary("diskfont.library",36))) {
  250.        /* OK, load font now */
  251.        if (gadfont=OpenDiskFont(tmobj->do_Font)) {
  252.         /* Set font */
  253.         SetFont(&tmprp,gadfont);
  254.         fheight=gadfont->tf_YSize+INTERHEIGHT+1;
  255.        }
  256.  
  257.        /* Close library again */
  258.        CloseLibrary(DiskfontBase);
  259.       }
  260.  
  261.       DEBUG_PRINTF("TextAttr: 0x%08lx",tmobj->do_Font);
  262.       DEBUG_PRINTF(" Font: 0x%08lx\n",gadfont);
  263.  
  264.       /* Scan tool list */
  265.       while (dt) {
  266.        ULONG valx=0,valy=0;
  267.  
  268.        if (text) {
  269.         /* Gadgets */
  270.         char *s=dt->dt_ExecName;
  271.  
  272.         /* Link and name valid? */
  273.         if (dt->dt_ExecLink && s) {
  274.          valx=TextLength(&tmprp,s,strlen(s))+2*INTERWIDTH+2;
  275.          valy=fheight;
  276.         }
  277.        } else {
  278.         /* Images */
  279.         struct TMLinkImage *tmli=dt->dt_ImageLink;
  280.  
  281.         /* Link to image valid? */
  282.         if (tmli) {
  283.          /* max(width) */
  284.          valx=tmli->tmli_Width;
  285.          valy=tmli->tmli_Height-1;
  286.         }
  287.        }
  288.  
  289.        /* Check maxima */
  290.        if (valx>maxx) maxx=valx;
  291.        if (valy>maxy) maxy=valy;
  292.  
  293.        /* Increment counter & Get pointer to next tool */
  294.        count++;
  295.        dt=dt->dt_Next;
  296.       }
  297.  
  298.       /* Calculate window sizes */
  299.       tmobj->do_Width=tmobj->do_Columns*maxx;
  300.       tmobj->do_Height=((count+tmobj->do_Columns-1)/tmobj->do_Columns)*maxy;
  301.       tmobj->do_XSize=maxx;
  302.       tmobj->do_YSize=maxy;
  303.      }
  304.  
  305.      /* Got valid window sizes? */
  306.      if (((LONG) tmobj->do_XSize>1) && ((LONG) tmobj->do_YSize>1) &&
  307.          (tmobj->do_Columns>0) && (tmobj->do_Columns<=100)) {
  308.       BOOL menu=(tmobj->do_Flags & DO_Menu)!=0;
  309.  
  310.       /* Correct window sizes */
  311.       if (borderless) {
  312.        /* Borderless window */
  313.        struct Gadget *g=&tmobj->do_DragGadget;
  314.  
  315.        /* Gadget window */
  316.        if (text) {
  317.         tmobj->do_Width--;
  318.         tmobj->do_Height--;
  319.        }
  320.  
  321.        /* Calculate drag gadget dimensions */
  322.        if (tmobj->do_Flags & DO_Vertical) {
  323.         /* Vertical drag gadget */
  324.         struct RastPort tmprp;
  325.         UWORD gwidth;
  326.  
  327.         /* Init RastPort for text writing */
  328.         InitRastPort(&tmprp);
  329.         SetFont(&tmprp,tf);
  330.         gwidth=TextLength(&tmprp,"A",1);
  331.  
  332.         tmobj->do_Left=gwidth;
  333.         tmobj->do_Top=0;
  334.         tmobj->do_Width+=gwidth;
  335.         g->Width=gwidth;
  336.         g->Height=tmobj->do_Height;
  337.        } else {
  338.         /* Horizontal drag gadget */
  339.         UWORD gheight=(tf->tf_YSize+8)/2;
  340.  
  341.         tmobj->do_Left=0;
  342.         tmobj->do_Top=gheight;
  343.         tmobj->do_Height+=gheight;
  344.         g->Width=tmobj->do_Width;
  345.         g->Height=gheight;
  346.        }
  347.  
  348.        /* Init drag gadget structure */
  349.        g->Flags=GFLG_GADGHNONE;
  350.        g->Activation=GACT_IMMEDIATE;
  351.        g->GadgetType=GTYP_SYSGADGET|GTYP_WDRAGGING;
  352.  
  353.        /* Get pens */
  354.        tmobj->do_FillPen=dri->dri_Pens[FILLPEN];
  355.        tmobj->do_BackPen=dri->dri_Pens[BACKGROUNDPEN];
  356.       } else {
  357.        /* Normal window */
  358.        tmobj->do_Left=pubsc->WBorLeft+1;
  359.        tmobj->do_Top=pubsc->WBorTop+tf->tf_YSize+2;
  360.        if (text) {
  361.         tmobj->do_Width++;
  362.         tmobj->do_Height++;
  363.        } else {
  364.         tmobj->do_Width+=2;
  365.         tmobj->do_Height+=2;
  366.        }
  367.       }
  368.  
  369.       /* Centered window? */
  370.       if (tmobj->do_Flags & DO_Centered) {
  371.        /* Centered */
  372.        /* Borderless window: X = MouseX - (width-left)/2 - left */
  373.        /* Normal window    : X = MouseX -        width/2 - left */
  374.        wx=tmobj->do_Width;
  375.        wy=tmobj->do_Height;
  376.  
  377.        /* Borderless window? */
  378.        if (borderless) {
  379.         wx-=tmobj->do_Left;
  380.         wy-=tmobj->do_Top;
  381.        }
  382.  
  383.        wx=pubsc->MouseX-wx/2-tmobj->do_Left;
  384.        wy=pubsc->MouseY-wy/2-tmobj->do_Top;
  385.       } else {
  386.        /* Not centered */
  387.        wx=tmobj->do_LeftEdge;
  388.        wy=tmobj->do_TopEdge;
  389.       }
  390.  
  391.       /* Dock with menu? */
  392.       if (menu &&
  393.           (tmobj->do_Menu=CreateMenus(DockMenu,GTMN_FullMenu, TRUE,
  394.                                                TAG_DONE)) &&
  395.           !LayoutMenus(tmobj->do_Menu,vi,GTMN_NewLookMenus, TRUE,
  396.                                          TAG_DONE)) {
  397.        FreeMenus(tmobj->do_Menu);
  398.        tmobj->do_Menu=NULL;
  399.       }
  400.  
  401.       DEBUG_PRINTF("Boxes: X %ld",tmobj->do_XSize);
  402.       DEBUG_PRINTF(" Y %ld",tmobj->do_YSize);
  403.       DEBUG_PRINTF(" Window: Width %ld",tmobj->do_Width);
  404.       DEBUG_PRINTF(" Height %ld\n",tmobj->do_Height);
  405.       DEBUG_PRINTF("menu %ld",menu);
  406.       DEBUG_PRINTF(" Menu 0x%08lx\n",tmobj->do_Menu);
  407.  
  408.       /* Open window */
  409.       if ((!menu || tmobj->do_Menu) &&
  410.           (w=OpenWindowTags(NULL,WA_Left,         wx,
  411.                                  WA_Top,          wy,
  412.                                  WA_InnerWidth,   tmobj->do_Width,
  413.                                  WA_InnerHeight,  tmobj->do_Height,
  414.                                  WA_Title,        tmobj->do_Title,
  415.                                  WA_DragBar,      !borderless,
  416.                                  WA_CloseGadget,  !borderless,
  417.                                  WA_DepthGadget,  !borderless,
  418.                                  WA_Borderless,   borderless,
  419.                                  WA_PubScreen,    pubsc,
  420.                                  WA_RMBTrap,      !menu,
  421.                                  WA_AutoAdjust,   TRUE,
  422.                                  WA_IDCMP,        0,
  423.                                  WA_NewLookMenus, TRUE,
  424.                                  TAG_DONE))) {
  425.        /* Backdrop window? */
  426.        if (tmobj->do_Flags & DO_Backdrop) WindowToBack(w);
  427.  
  428.        /* Set window pointers */
  429.        w->UserPort=IDCMPPort;
  430.        w->UserData=(APTR) tmobj;
  431.  
  432.        DEBUG_PRINTF("Window: 0x%08lx\n",w);
  433.  
  434.        /* Set IDCMP flags */
  435.        if (ModifyIDCMP(w,IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_GADGETUP|
  436.                          IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|IDCMP_MENUPICK|
  437.                          IDCMP_REFRESHWINDOW)) {
  438.         struct Gadget *g;
  439.         BOOL wbscreen=(pubsc->Flags & SCREENTYPE)==WBENCHSCREEN;
  440.  
  441.         /* Try to add the window as application window */
  442.         tmobj->do_AppWindow=NULL;
  443.         if (wbscreen && GetWorkbench() &&
  444.             !(tmobj->do_AppWindow=AddAppWindowA((ULONG) &tmobj->do_Link,
  445.                                                 NULL,w,AppMsgPort,NULL)))
  446.          /* AddAppWindow() failed (Workbench not running?) */
  447.          FreeWorkbench();
  448.  
  449.         /* Draw drag gadget */
  450.         if (borderless) {
  451.          struct RastPort *rp=w->RPort;
  452.          UWORD width=tmobj->do_DragGadget.Width-1;
  453.          UWORD height=tmobj->do_DragGadget.Height-1;
  454.  
  455.          /* Draw lighted side */
  456.          SetAPen(rp,dri->dri_Pens[SHINEPEN]);
  457.          Move(rp,0,height);
  458.          Draw(rp,0,0);
  459.          Draw(rp,width,0);
  460.  
  461.          /* Draw shadowed side */
  462.          SetAPen(rp,dri->dri_Pens[SHADOWPEN]);
  463.          Move(rp,width,1);
  464.          Draw(rp,width,height);
  465.          Draw(rp,0,height);
  466.  
  467.          AddGadget(w,&tmobj->do_DragGadget,(UWORD) -1);
  468.          RefreshGList(&tmobj->do_DragGadget,w,NULL,1);
  469.         }
  470.  
  471.         /* Draw initial window state */
  472.         {
  473.          struct RastPort *rp=w->RPort;
  474.          ULONG col=0,lin=0;
  475.          UWORD x=tmobj->do_Left;
  476.          UWORD y=tmobj->do_Top;
  477.          UWORD dw=tmobj->do_XSize;
  478.          UWORD dh=tmobj->do_YSize;
  479.          BOOL pattern=((tmobj->do_Flags & DO_Pattern)!=0 && !text);
  480.          struct NewGadget ng;
  481.  
  482.          /* Set pattern */
  483.          if (pattern) {
  484.           SetAPen(rp,dri->dri_Pens[SHADOWPEN]);
  485.           SetDrMd(rp,JAM2);
  486.           SetAfPt(rp,BackgroundPattern,1);
  487.          }
  488.  
  489.          /* Set pointer to begin of tool list */
  490.          dt=tmobj->do_Tools;
  491.  
  492.          /* Init TextAttr & NewGadget struct, create GadTools context */
  493.          if (text) {
  494.           /* Font set? */
  495.           if (tmobj->do_Font)
  496.            tmobj->do_TextAttr=*(tmobj->do_Font);
  497.           else {
  498.            /* No. Set screen font */
  499.            tmobj->do_TextAttr.ta_Name=tf->tf_Message.mn_Node.ln_Name;
  500.            tmobj->do_TextAttr.ta_YSize=tf->tf_YSize;
  501.            tmobj->do_TextAttr.ta_Style=tf->tf_Style;
  502.            tmobj->do_TextAttr.ta_Flags=tf->tf_Flags;
  503.           }
  504.  
  505.           DEBUG_PRINTF("Font '%s'",tmobj->do_TextAttr.ta_Name);
  506.           DEBUG_PRINTF(" Size %ld\n",tmobj->do_TextAttr.ta_YSize);
  507.  
  508.           ng.ng_Width=dw-1;
  509.           ng.ng_Height=dh-1;
  510.           ng.ng_TextAttr=&tmobj->do_TextAttr;
  511.           ng.ng_Flags=PLACETEXT_IN;
  512.           ng.ng_VisualInfo=vi;
  513.           ng.ng_UserData=0;
  514.           tmobj->do_GadToolsGadgets=NULL;
  515.           if (!(g=CreateContext(&tmobj->do_GadToolsGadgets)))
  516.            dt=NULL; /* Error!!! */
  517.          }
  518.  
  519.          /* Scan tool list */
  520.          while (dt) {
  521.           if (text) {
  522.            /* Gadgets. Link valid? */
  523.            if (dt->dt_ExecLink) {
  524.             /* Init NewGadget values */
  525.             ng.ng_LeftEdge=x;
  526.             ng.ng_TopEdge=y;
  527.             ng.ng_GadgetText=dt->dt_ExecName;
  528.             ng.ng_UserData=dt;
  529.  
  530.             /* Create button gadget */
  531.             if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE)))
  532.              dt=NULL; /* Error!!!! */
  533.            }
  534.           } else {
  535.            /* Images */
  536.            struct TMLinkImage *tmli=dt->dt_ImageLink;
  537.  
  538.            /* Draw pattern? */
  539.            if (pattern) {
  540.             /* Set Pattern color */
  541.             SetBPen(rp,(col+lin)&1 ? dri->dri_Pens[BACKGROUNDPEN] :
  542.                                      dri->dri_Pens[FILLPEN]);
  543.  
  544.             /* Draw pattern */
  545.             RectFill(rp,x,y,x+dw-1,y+dh-1);
  546.            }
  547.  
  548.            /* Link valid? */
  549.            if (tmli) {
  550.             /* Yes. Set Parameters */
  551.             tmli->tmli_LeftEdge=x+(dw - tmli->tmli_Width)/2;
  552.             tmli->tmli_TopEdge=y+(dh + 1 - tmli->tmli_Height)/2;
  553.             tmli->tmli_RastPort=w->RPort;
  554.  
  555.             /* Draw deactivated state */
  556.             CallActivateTMObject((struct TMLink *) tmli,(void *) IOC_DEACTIVE);
  557.            }
  558.           }
  559.  
  560.           /* Next column */
  561.           col++;
  562.  
  563.           /* Increment x,y. Last Column? */
  564.           if (col==tmobj->do_Columns) {
  565.            /* Yes */
  566.            y+=dh;
  567.            x=tmobj->do_Left;
  568.            col=0;
  569.            lin++;
  570.           } else
  571.            /* No */
  572.            x+=dw;
  573.  
  574.           /* Get pointer to next node */
  575.           if (dt) dt=dt->dt_Next;
  576.          }
  577.  
  578.          /* Reset Areafill pattern */
  579.          if (pattern) SetAfPt(rp,NULL,0);
  580.         }
  581.  
  582.         /* All OK. */
  583.         if (!text || g) {
  584.          /* Add GadTools gadgets */
  585.          if (text) {
  586.           AddGList(w,tmobj->do_GadToolsGadgets,(UWORD) -1,(UWORD) -1,NULL);
  587.           RefreshGList(tmobj->do_GadToolsGadgets,w,NULL,(UWORD) -1);
  588.           GT_RefreshWindow(w,NULL);
  589.          }
  590.  
  591.          /* Add menu */
  592.          if (menu) SetMenuStrip(w,tmobj->do_Menu);
  593.  
  594.          /* Free resources */
  595.          FreeScreenDrawInfo(pubsc,dri);
  596.          UnlockPubScreen(NULL,pubsc);
  597.  
  598.          /* Save pointers */
  599.          tmobj->do_VisualInfo=vi;
  600.          tmobj->do_TextFont=tf;
  601.          tmobj->do_GadgetFont=gadfont;
  602.          tmobj->do_Window=w;
  603.          tmobj->do_DeferClose=FALSE;
  604.          return;
  605.          /* NOT REACHED */
  606.         }
  607.  
  608.         /* Remove drag Gadget */
  609.         if (borderless) RemoveGadget(w,&tmobj->do_DragGadget);
  610.  
  611.         /* Free GadTools gadgets */
  612.         if (text) {
  613.          FreeGadgets(tmobj->do_GadToolsGadgets);
  614.          tmobj->do_GadToolsGadgets=NULL;
  615.         }
  616.  
  617.         /* Remove AppWindow, close Workbench */
  618.         if (tmobj->do_AppWindow) {
  619.          SafeRemoveAppWindow(tmobj->do_AppWindow,&tmobj->do_Link);
  620.          FreeWorkbench();
  621.         }
  622.        }
  623.        SafeCloseWindow(w);
  624.       }
  625.       if (tmobj->do_Menu) {
  626.        FreeMenus(tmobj->do_Menu);
  627.        tmobj->do_Menu=NULL;
  628.       }
  629.      }
  630.      if (gadfont) CloseFont(gadfont);
  631.      CloseFont(tf);
  632.     }
  633.     FreeVisualInfo(vi);
  634.    }
  635.    FreeScreenDrawInfo(pubsc,dri);
  636.   }
  637.   UnlockPubScreen(NULL,pubsc);
  638.  }
  639.  
  640.  /* Dock couldn't be opened! */
  641.  if (beep)
  642.   DisplayBeep(NULL);
  643.  else
  644.   tmobj->do_ReOpen = TRUE;
  645. }
  646.  
  647. /* Close Dock window */
  648. static void CloseDockWindow(struct TMObjectDock *tmobj)
  649. {
  650.  struct DockTool *dt=tmobj->do_Tools;
  651.  struct Window *w=tmobj->do_Window;
  652.  
  653.  DEBUG_PRINTF("CloseDockWindow: 0x%08lx\n",tmobj);
  654.  
  655.  /* Deactivate all Image objects */
  656.  while (dt) {
  657.   /* Image object active? */
  658.   if (dt->dt_ImageLink && dt->dt_ImageLink->tmli_Link.tml_Active)
  659.    /* Yes. Deactivate it first */
  660.    CallActivateTMObject((struct TMLink *) dt->dt_ImageLink,
  661.                         (void *) IOC_DEACTIVE);
  662.  
  663.   /* Get pointer to next node */
  664.   dt=dt->dt_Next;
  665.  }
  666.  
  667.  /* Remove menu */
  668.  if (tmobj->do_Menu) {
  669.   ClearMenuStrip(w);
  670.   FreeMenus(tmobj->do_Menu);
  671.   tmobj->do_Menu=NULL;
  672.  }
  673.  
  674.  /* Remove drag gadget */
  675.  if (!tmobj->do_Title) RemoveGadget(w,&tmobj->do_DragGadget);
  676.  
  677.  /* Remove gadtools gadgets */
  678.  if (tmobj->do_GadToolsGadgets) {
  679.   RemoveGList(w,tmobj->do_GadToolsGadgets,(UWORD) -1);
  680.   FreeGadgets(tmobj->do_GadToolsGadgets);
  681.   tmobj->do_GadToolsGadgets=NULL;
  682.  }
  683.  
  684.  /* Remove AppWindow, free Workbench */
  685.  if (tmobj->do_AppWindow) {
  686.   SafeRemoveAppWindow(tmobj->do_AppWindow,&tmobj->do_Link);
  687.   FreeWorkbench();
  688.  }
  689.  
  690.  /* Sticky window? */
  691.  if (!(tmobj->do_Flags & DO_Sticky)) {
  692.   /* No, remember last window position */
  693.   tmobj->do_LeftEdge=w->LeftEdge;
  694.   tmobj->do_TopEdge=w->TopEdge;
  695.  }
  696.  
  697.  /* Close Window */
  698.  SafeCloseWindow(w);
  699.  tmobj->do_Window=NULL;
  700.  
  701.  /* Free resources */
  702.  if (tmobj->do_GadgetFont) CloseFont(tmobj->do_GadgetFont);
  703.  CloseFont(tmobj->do_TextFont);
  704.  FreeVisualInfo(tmobj->do_VisualInfo);
  705. }
  706.  
  707. /* If dock window is on the screen then close it and set the re-open flag */
  708. void ScreenCloseRequest(struct TMObject *tmobj, struct Screen *s)
  709. {
  710.  struct TMObjectDock *tmdo = (struct TMObjectDock *) tmobj;
  711.  
  712.  /* Window open and on the screen? */
  713.  if (tmdo->do_Window && (tmdo->do_Window->WScreen == s)) {
  714.  
  715.   /* Yes, close dock */
  716.   CloseDockWindow(tmdo);
  717.  
  718.   /* Set re-open flag */
  719.   tmdo->do_ReOpen = TRUE;
  720.  }
  721. }
  722.  
  723. /* If the re-open flag is set then open the dock again */
  724. void ScreenOpenRequest(struct TMObj *tmobj, char *name)
  725. {
  726.  struct TMObjectDock *tmdo = (struct TMObjectDock *) tmobj;
  727.  
  728.  /* Re-open flag set and public screen name matches? */
  729.  if (tmdo->do_ReOpen && tmdo->do_PubScreen && !stricmp(tmdo->do_PubScreen, name)) {
  730.  
  731.   /* Yes, open dock */
  732.   OpenDockWindow(tmdo, TRUE);
  733.  
  734.   /* Reset re-open flag */
  735.   tmdo->do_ReOpen = FALSE;
  736.  }
  737. }
  738.  
  739.  
  740. /* Free tools list */
  741. static void FreeTools(struct TMObjectDock *tmobj)
  742. {
  743.  struct DockTool *dt,*nextdt=tmobj->do_Tools;
  744.  
  745.  /* Scan list */
  746.  while (dt=nextdt) {
  747.   /* Get pointer to next node */
  748.   nextdt=dt->dt_Next;
  749.  
  750.   /* Remove links */
  751.   if (dt->dt_ExecLink) RemLinkTMObject(dt->dt_ExecLink);
  752.   if (dt->dt_ImageLink) RemLinkTMObject((struct TMLink *) dt->dt_ImageLink);
  753.   if (dt->dt_SoundLink) RemLinkTMObject(dt->dt_SoundLink);
  754.  
  755.   /* Free Node */
  756.   FreeMem(dt,sizeof(struct DockTool));
  757.  }
  758. }
  759.  
  760. /* Create a Dock object */
  761. struct TMObject *CreateTMObjectDock(struct TMHandle *handle, char *name,
  762.                                     struct TagItem *tags)
  763. {
  764.  struct TMObjectDock *tmobj;
  765.  
  766.  /* allocate memory for object */
  767.  if (tmobj=(struct TMObjectDock *)
  768.             AllocateTMObject(sizeof(struct TMObjectDock))) {
  769.   struct TagItem *ti,*tstate;
  770.   struct DockTool *dt=NULL;
  771.  
  772.   /* Set defaults */
  773.   tmobj->do_Columns=1;
  774.  
  775.   /* Scan tag list */
  776.   tstate=tags;
  777.   while (ti=NextTagItem(&tstate)) {
  778.  
  779.    DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  780.  
  781.    switch (ti->ti_Tag) {
  782.     case TMOP_Columns:   if (ti->ti_Data) tmobj->do_Columns=ti->ti_Data;
  783.                          break;
  784.     case TMOP_Font:      {
  785.                           struct TextAttr *ta=(struct TextAttr *) ti->ti_Data;
  786.  
  787.                           if (ta && ta->ta_Name) tmobj->do_Font=ta;
  788.                          }
  789.                          break;
  790.     case TMOP_HotKey:    tmobj->do_HotKey=(char *) ti->ti_Data;
  791.                          break;
  792.     case TMOP_LeftEdge:  tmobj->do_LeftEdge=ti->ti_Data;
  793.                          break;
  794.     case TMOP_PubScreen: tmobj->do_PubScreen=(char *) ti->ti_Data;
  795.                          break;
  796.     case TMOP_Title:     tmobj->do_Title=(char *) ti->ti_Data;
  797.                          break;
  798.     case TMOP_Tool:      if (ti->ti_Data) {
  799.                           struct DockTool *newdt;
  800.  
  801.                           /* Alloc DockTool structure */
  802.                           if (newdt=AllocMem(sizeof(struct DockTool),
  803.                                              MEMF_CLEAR)) {
  804.                            char **names=(char **) ti->ti_Data;
  805.  
  806.                            /* Add link to Exec object */
  807.                            if (names[0] &&
  808.                                (newdt->dt_ExecLink=AddLinkTMObject(handle,
  809.                                                                   names[0],
  810.                                                                 TMOBJTYPE_EXEC,
  811.                                                             (struct TMObject *)
  812.                                                                   tmobj)))
  813.                             /* Get name of exec object. We use names[0]
  814.                                instead of object name, because the link could
  815.                                be deleted while window is still active. */
  816.                             newdt->dt_ExecName=names[0];
  817.  
  818.                            /* Add link to Image object */
  819.                            if (names[1])
  820.                             newdt->dt_ImageLink=(struct TMLinkImage *)
  821.                                     AddLinkTMObject(handle,names[1],
  822.                                                     TMOBJTYPE_IMAGE,
  823.                                                     (struct TMObject *) tmobj);
  824.  
  825.                            /* Add link to Sound object */
  826.                            if (names[2])
  827.                             newdt->dt_SoundLink=AddLinkTMObject(handle,names[2],
  828.                                                                 TMOBJTYPE_SOUND,
  829.                                                             (struct TMObject *)
  830.                                                                 tmobj);
  831.  
  832.                            /* Add node to list. Head of list? */
  833.                            if (dt) {
  834.                             /* No. Add to tail */
  835.                             dt->dt_Next=newdt;
  836.                             dt=newdt;
  837.                            } else {
  838.                             /* Yes. Init list anchor */
  839.                             tmobj->do_Tools=newdt;
  840.                             dt=newdt;
  841.                            }
  842.                           }
  843.                          }
  844.                          break;
  845.     case TMOP_TopEdge:   tmobj->do_TopEdge=ti->ti_Data;
  846.                          break;
  847.    }
  848.   }
  849.  
  850.   {
  851.    BOOL hotkey=tmobj->do_HotKey!=NULL;
  852.  
  853.    /* No HotKey or cannot create CxObject from HotKey description? */
  854.    if (hotkey && (tmobj->do_CxObj=HotKey(tmobj->do_HotKey,BrokerPort,
  855.                                          (ULONG) &tmobj->do_Link))) {
  856.  
  857.     DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->do_CxObj);
  858.  
  859.     /* Attach object to broker */
  860.     AttachCxObj(Broker,tmobj->do_CxObj);
  861.    }
  862.  
  863.    /* No HotKey or Commodities error? */
  864.    if (!hotkey || (tmobj->do_CxObj && !CxObjError(Broker))) {
  865.     /* Set flags */
  866.     tmobj->do_Flags=PackBoolTags(DO_Activated,tags,flagmap);
  867.  
  868.     /* Initialize rest of structure */
  869.     tmobj->do_Link.tml_Linked=(struct TMObject *) tmobj;
  870.  
  871.     /* Active flag set? */
  872.     if (tmobj->do_Flags & DO_Activated)
  873.      /* Yes. Open dock window */
  874.      OpenDockWindow(tmobj, FALSE);
  875.  
  876.     /* All OK */
  877.     return(tmobj);
  878.    }
  879.  
  880.    /* Free resources */
  881.    if (tmobj->do_CxObj) SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  882.   }
  883.   FreeTools(tmobj);
  884.  }
  885.  
  886.  /* call failed */
  887.  return(NULL);
  888. }
  889.  
  890. /* Delete a Dock object */
  891. BOOL DeleteTMObjectDock(struct TMObjectDock *tmobj)
  892. {
  893.  DEBUG_PRINTF("Delete/Dock (0x%08lx)\n",tmobj);
  894.  
  895.  /* Remove links */
  896.  DeleteAllLinksTMObject((struct TMObject *) tmobj);
  897.  
  898.  /* Free resources */
  899.  if (tmobj->do_CxObj) SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  900.  
  901.  /* Close window and free its resources */
  902.  if (tmobj->do_Window) CloseDockWindow(tmobj);
  903.  
  904.  /* Free tool nodes */
  905.  FreeTools(tmobj);
  906.  
  907.  /* Remove object from list */
  908.  Remove((struct Node *) tmobj);
  909.  
  910.  /* Free object */
  911.  FreeMem(tmobj,sizeof(struct TMObjectDock));
  912.  
  913.  /* All OK. */
  914.  return(TRUE);
  915. }
  916.  
  917. /* Change a Dock object */
  918. struct TMObject *ChangeTMObjectDock(struct TMHandle *handle,
  919.                                     struct TMObjectDock *tmobj,
  920.                                     struct TagItem *tags)
  921. {
  922.  struct TagItem *ti,*tstate;
  923.  struct DockTool *dt;
  924.  
  925.  /* Search last dock tool */
  926.  dt=tmobj->do_Tools;
  927.  if (dt)
  928.   while (dt->dt_Next) dt=dt->dt_Next;
  929.  
  930.  /* Close dock */
  931.  if (tmobj->do_Window) CloseDockWindow(tmobj);
  932.  
  933.  /* Scan tag list */
  934.  tstate=tags;
  935.  while (ti=NextTagItem(&tstate)) {
  936.  
  937.   DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  938.  
  939.   switch (ti->ti_Tag) {
  940.    case TMOP_Columns:   if (ti->ti_Data) tmobj->do_Columns=ti->ti_Data;
  941.                         break;
  942.    case TMOP_Font:      {
  943.                          struct TextAttr *ta=(struct TextAttr *) ti->ti_Data;
  944.  
  945.                          if (ta && ta->ta_Name) tmobj->do_Font=ta;
  946.                         }
  947.                         break;
  948.    case TMOP_HotKey:    if (tmobj->do_CxObj) {
  949.                          SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  950.                          tmobj->do_CxObj=NULL;
  951.                         }
  952.  
  953.                         tmobj->do_HotKey=(char *) ti->ti_Data;
  954.                         break;
  955.    case TMOP_LeftEdge:  tmobj->do_LeftEdge=ti->ti_Data;
  956.                         break;
  957.    case TMOP_PubScreen: tmobj->do_PubScreen=(char *) ti->ti_Data;
  958.                         break;
  959.    case TMOP_Title:     tmobj->do_Title=(char *) ti->ti_Data;
  960.                         break;
  961.    case TMOP_Tool:      if (ti->ti_Data) {
  962.                          struct DockTool *newdt;
  963.  
  964.                          /* Alloc DockTool structure */
  965.                          if (newdt=AllocMem(sizeof(struct DockTool),
  966.                                             MEMF_CLEAR)) {
  967.                           char **names=(char **) ti->ti_Data;
  968.  
  969.                           /* Add link to Exec object */
  970.                           if (names[0] &&
  971.                               (newdt->dt_ExecLink=AddLinkTMObject(handle,
  972.                                                                   names[0],
  973.                                                                 TMOBJTYPE_EXEC,
  974.                                                             (struct TMObject *)
  975.                                                                   tmobj)))
  976.                            /* Get name of exec object. We use names[0]
  977.                               instead of object name, because the link could
  978.                               be deleted while window is still active. */
  979.                            newdt->dt_ExecName=names[0];
  980.  
  981.                           /* Add link to Image object */
  982.                           if (names[1])
  983.                            newdt->dt_ImageLink=(struct TMLinkImage *)
  984.                                     AddLinkTMObject(handle,names[1],
  985.                                                     TMOBJTYPE_IMAGE,
  986.                                                     (struct TMObject *) tmobj);
  987.  
  988.                           /* Add link to Sound object */
  989.                           if (names[2])
  990.                            newdt->dt_SoundLink=AddLinkTMObject(handle,names[2],
  991.                                                                TMOBJTYPE_SOUND,
  992.                                                            (struct TMObject *)
  993.                                                                tmobj);
  994.  
  995.                           /* Add node to list. Head of list? */
  996.                           if (dt) {
  997.                            /* No. Add to tail */
  998.                            dt->dt_Next=newdt;
  999.                            dt=newdt;
  1000.                           } else {
  1001.                            /* Yes. Init list anchor */
  1002.                            tmobj->do_Tools=newdt;
  1003.                            dt=newdt;
  1004.                           }
  1005.                          }
  1006.                         }
  1007.                         break;
  1008.    case TMOP_TopEdge:   tmobj->do_TopEdge=ti->ti_Data;
  1009.                         break;
  1010.   }
  1011.  }
  1012.  
  1013.  /* Set new flags */
  1014.  tmobj->do_Flags=PackBoolTags(tmobj->do_Flags,tags,flagmap);
  1015.  
  1016.  /* HotKey set? Create Commodities object from HotKey description */
  1017.  if (tmobj->do_HotKey && !tmobj->do_CxObj &&
  1018.      (tmobj->do_CxObj=HotKey(tmobj->do_HotKey,BrokerPort,
  1019.                              (ULONG) &tmobj->do_Link))) {
  1020.  
  1021.   DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->do_CxObj);
  1022.  
  1023.   /* Attach object to broker */
  1024.   AttachCxObj(Broker,tmobj->do_CxObj);
  1025.  
  1026.   /* Commodities error? */
  1027.   if (CxObjError(Broker)) {
  1028.    SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  1029.    tmobj->do_CxObj=NULL;
  1030.   }
  1031.  }
  1032.  
  1033.  /* Active flag set? */
  1034.  if (tmobj->do_Flags & DO_Activated)
  1035.   /* Yes. Open dock window */
  1036.   OpenDockWindow(tmobj, FALSE);
  1037.  
  1038.  /* All OK. */
  1039.  return(TRUE);
  1040. }
  1041.  
  1042. /* Allocate & Initialize a TMLink structure */
  1043. struct TMLink *AllocLinkTMObjectDock(struct TMObjectDock *tmobj)
  1044. {
  1045.  struct TMLink *tml;
  1046.  
  1047.  /* Allocate memory for link structure */
  1048.  if (tml=AllocMem(sizeof(struct TMLink),MEMF_CLEAR|MEMF_PUBLIC))
  1049.   /* Initialize link structure */
  1050.   tml->tml_Size=sizeof(struct TMLink);
  1051.  
  1052.  return(tml);
  1053. }
  1054.  
  1055. /* Update link structures */
  1056. void DeleteLinkTMObjectDock(struct TMLink *tml)
  1057. {
  1058.  struct TMObjectDock *tmobj=(struct TMObjectDock *) tml->tml_LinkedTo;
  1059.  struct DockTool *dt=tmobj->do_Tools;
  1060.  
  1061.  /* Scan tool list */
  1062.  while (dt) {
  1063.   /* Link to Exec object? */
  1064.   if (tml==dt->dt_ExecLink) {
  1065.    dt->dt_ExecLink=NULL;
  1066.    dt->dt_ExecName=NULL;
  1067.    break;
  1068.   }
  1069.   /* Link to Image object? */
  1070.   else if (tml==(struct TMLink *) dt->dt_ImageLink) {
  1071.    /* Image object active? */
  1072.    if (tml->tml_Active)
  1073.     /* Yes. Deactivate it */
  1074.     CallActivateTMObject((struct TMLink *) tml,(void *) IOC_DEACTIVE);
  1075.  
  1076.    dt->dt_ImageLink=NULL;
  1077.    break;
  1078.   }
  1079.   /* Link to Sound object? */
  1080.   else if (tml==dt->dt_SoundLink) {
  1081.    dt->dt_SoundLink=NULL;
  1082.    break;
  1083.   }
  1084.  
  1085.   /* Get pointer to next tool */
  1086.   dt=dt->dt_Next;
  1087.  }
  1088. }
  1089.  
  1090. /* Find dock tool that corresponds to X,Y position */
  1091. static struct DockTool *FindDockTool(struct TMObjectDock *tmobj, ULONG x,
  1092.                                      ULONG y)
  1093. {
  1094.  struct DockTool *dt;
  1095.  UWORD dx=tmobj->do_Left;
  1096.  UWORD dy=tmobj->do_Top;
  1097.  UWORD w,h;
  1098.  ULONG col,cols;
  1099.  
  1100.  /* Out of bounds? */
  1101.  if ((x<dx) || (y<dy)) return(NULL); /* Yes! */
  1102.  
  1103.  /* Init variables */
  1104.  dt=tmobj->do_Tools;
  1105.  w=tmobj->do_XSize;
  1106.  h=tmobj->do_YSize;
  1107.  cols=tmobj->do_Columns;
  1108.  col=0;
  1109.  
  1110.  /* Scan dock tool list */
  1111.  while (dt)
  1112.   if ((x>=dx) && (y>=dy) && (x<dx+w) && (y<dy+h)) {
  1113.    /* Tool found */
  1114.    tmobj->do_Selected=dt;
  1115.    tmobj->do_SelectX=dx;
  1116.    tmobj->do_SelectY=dy;
  1117.    return(dt);
  1118.   } else {
  1119.    /* Increment column counter */
  1120.    col++;
  1121.  
  1122.    /* Last column? */
  1123.    if (col==cols) {
  1124.     /* Yes */
  1125.     dx=tmobj->do_Left;
  1126.     dy+=h;
  1127.     col=0;
  1128.    } else
  1129.     /* No */
  1130.     dx+=w;
  1131.  
  1132.    /* Get pointer to next dock tool */
  1133.    dt=dt->dt_Next;
  1134.   }
  1135.  
  1136.  /* Dock tool not found */
  1137.  return(NULL);
  1138. }
  1139.  
  1140. /* Activate one dock entry */
  1141. static BOOL ActivateDockEntry(struct TMObjectDock *tmobj, struct DockTool *dt,
  1142.                               struct AppMessage *msg, ULONG anim)
  1143. {
  1144.  /* Activate Sound object */
  1145.  if (dt->dt_SoundLink) CallActivateTMObject(dt->dt_SoundLink,NULL);
  1146.  
  1147.  /* Activate Image object */
  1148.  if (!(tmobj->do_Flags & DO_Text) && dt->dt_ImageLink && anim)
  1149.     CallActivateTMObject((struct TMLink *) dt->dt_ImageLink,(void *) anim);
  1150.  
  1151.  /* Set defered close flag */
  1152.  tmobj->do_DeferClose=TRUE;
  1153.  
  1154.  /* Activate Exec object */
  1155.  if (dt->dt_ExecLink) CallActivateTMObject(dt->dt_ExecLink,msg);
  1156.  
  1157.  /* PopUp dock or defered close? Yes, close window */
  1158.  if ((tmobj->do_Flags & DO_PopUp) || !tmobj->do_DeferClose)
  1159.   return(TRUE);
  1160.  else {
  1161.   /* Reset defered close flag */
  1162.   tmobj->do_DeferClose=FALSE;
  1163.   return(FALSE);
  1164.  }
  1165. }
  1166.  
  1167. /* Activate a Dock object */
  1168. void ActivateTMObjectDock(struct TMLink *tml, struct AppMessage *msg)
  1169. {
  1170.  struct TMObjectDock *tmobj=(struct TMObjectDock *) tml->tml_Linked;
  1171.  
  1172.  DEBUG_PRINTF("Activate/Dock (0x%08lx)\n",msg);
  1173.  
  1174.  /* Got arguments? */
  1175.  if (msg) {
  1176.   /* Yes. Icons were dropped on the dock */
  1177.   struct DockTool *dt;
  1178.  
  1179.   /* Find Tool */
  1180.   if (dt=FindDockTool(tmobj,msg->am_MouseX,msg->am_MouseY)) {
  1181.    /* Activate dock entry */
  1182.    if (ActivateDockEntry(tmobj,dt,msg,IOC_FULLANIM))
  1183.     CloseDockWindow(tmobj);
  1184.  
  1185.    /* Clear pointer */
  1186.    tmobj->do_Selected=NULL;
  1187.   }
  1188.  }
  1189.  /* No. User pressed HotKey. Window open? */
  1190.  else if (tmobj->do_Window)
  1191.   /* Defered close? */
  1192.   if (tmobj->do_DeferClose)
  1193.    /* Yes, clear flag */
  1194.    tmobj->do_DeferClose=FALSE;
  1195.   else
  1196.    /* No, close window and free its resources */
  1197.    CloseDockWindow(tmobj);
  1198.  else {
  1199.   /* Window not open. Open it. */
  1200.   OpenDockWindow(tmobj, TRUE);
  1201.  
  1202.   /* If DO_FrontMost is not set, move screen to front */
  1203.   if (!(tmobj->do_Flags & DO_FrontMost) && tmobj->do_Window)
  1204.    ScreenToFront(tmobj->do_Window->WScreen);
  1205.  }
  1206. }
  1207.  
  1208. /* Handle IDCMP events */
  1209. void HandleIDCMPEvents(void)
  1210. {
  1211.  struct IntuiMessage *msg;
  1212.  
  1213.  /* Scan IDCMP message port */
  1214.  while (msg=GT_GetIMsg(IDCMPPort)) {
  1215.   struct TMObjectDock *tmobj=(struct TMObjectDock *) msg->IDCMPWindow->UserData;
  1216.   BOOL closewindow=FALSE;
  1217.  
  1218.   DEBUG_PRINTF("IDCMP Class: 0x%08lx\n",msg->Class);
  1219.  
  1220.   switch (msg->Class) {
  1221.    case IDCMP_CLOSEWINDOW:    /* Set close flag */
  1222.                               closewindow=TRUE;
  1223.                               break;
  1224.    case IDCMP_REFRESHWINDOW:  {
  1225.                                struct Window *w=tmobj->do_Window;
  1226.  
  1227.                                GT_BeginRefresh(w);
  1228.                                GT_EndRefresh(w,TRUE);
  1229.                               }
  1230.                               break;
  1231.    case IDCMP_MOUSEBUTTONS:   /* Only docks with images need button events */
  1232.                               if (!(tmobj->do_Flags & DO_Text))
  1233.                                switch (msg->Code) {
  1234.                                 case SELECTDOWN: /* Select button pressed */
  1235.                                  {
  1236.                                   struct DockTool *dt;
  1237.  
  1238.                                   if (dt=FindDockTool(tmobj,msg->MouseX,
  1239.                                                             msg->MouseY)) {
  1240.                                    struct TMLinkImage *tmli=dt->dt_ImageLink;
  1241.  
  1242.                                    DEBUG_PRINTF("Dock selected: 0x%08lx\n",dt);
  1243.  
  1244.                                    /* Got a dock tool with image object? */
  1245.                                    if (tmli)
  1246.                                     /* Image object with active anim? */
  1247.                                     if (tmli->tmli_Link.tml_Active)
  1248.                                      /* Yes, clear pointer */
  1249.                                      tmobj->do_Selected=NULL;
  1250.                                     else
  1251.                                      /* No, select it */
  1252.                                      CallActivateTMObject((struct TMLink *)
  1253.                                                           tmli,
  1254.                                                           (void *) IOC_ACTIVE);
  1255.                                   }
  1256.                                  }
  1257.                                  break;
  1258.                                 case SELECTUP:   /* Select button released */
  1259.                                  {
  1260.                                   struct DockTool *dt=tmobj->do_Selected;
  1261.  
  1262.                                   /* Got a selected dock tool? */
  1263.                                   if (dt) {
  1264.                                    struct TMLinkImage *tmli=dt->dt_ImageLink;
  1265.  
  1266.                                    /* Dock tool with image object? */
  1267.                                    if (tmli) {
  1268.                                     UWORD x=msg->MouseX;
  1269.                                     UWORD y=msg->MouseY;
  1270.                                     UWORD dx=tmobj->do_SelectX;
  1271.                                     UWORD dy=tmobj->do_SelectY;
  1272.  
  1273.                                     /* Mouse still on dock tool and no */
  1274.                                     /* double click?                   */
  1275.                                     if ((x>=dx) && (y>=dy) &&
  1276.                                         (x<dx+tmobj->do_XSize) &&
  1277.                                         (y<dy+tmobj->do_YSize) &&
  1278.                                         !DoubleClick(tmobj->do_Seconds,
  1279.                                                      tmobj->do_Micros,
  1280.                                                      msg->Seconds,
  1281.                                                      msg->Micros)) {
  1282.                                      /* Yes. Activate dock entry */
  1283.                                      closewindow=ActivateDockEntry(tmobj,dt,
  1284.                                                             NULL,IOC_CONTANIM);
  1285.  
  1286.                                      /* Save time stamp */
  1287.                                      tmobj->do_Seconds=msg->Seconds;
  1288.                                      tmobj->do_Micros=msg->Micros;
  1289.                                     }
  1290.                                     else
  1291.                                      /* No, de-select image */
  1292.                                      CallActivateTMObject((struct TMLink *)
  1293.                                                           dt->dt_ImageLink,
  1294.                                                           (void *) IOC_DEACTIVE
  1295.                                                          );
  1296.                                    }
  1297.  
  1298.                                    /* Clear pointer */
  1299.                                    tmobj->do_Selected=NULL;
  1300.                                   }
  1301.                                  }
  1302.                                  break;
  1303.                                }
  1304.                               break;
  1305.    case IDCMP_GADGETUP:       /* Prevent double clicks */
  1306.                               if (!DoubleClick(tmobj->do_Seconds,
  1307.                                                tmobj->do_Micros,
  1308.                                                msg->Seconds,msg->Micros)) {
  1309.                                struct DockTool *dt=(struct DockTool *)
  1310.                                 ((struct Gadget *) msg->IAddress)->UserData;
  1311.  
  1312.                                /* Activate dock entry */
  1313.                                closewindow=ActivateDockEntry(tmobj,dt,NULL,0);
  1314.  
  1315.                                /* Save time stamp */
  1316.                                tmobj->do_Seconds=msg->Seconds;
  1317.                                tmobj->do_Micros=msg->Micros;
  1318.                               }
  1319.                               break;
  1320.    case IDCMP_MENUPICK:       {
  1321.                                USHORT menunum=msg->Code;
  1322.  
  1323.                                /* Scan all menu events */
  1324.                                while (menunum!=MENUNULL) {
  1325.                                 struct MenuItem *menuitem=
  1326.                                  ItemAddress(tmobj->do_Menu,menunum);
  1327.  
  1328.                                 /* Which menu selected? */
  1329.                                 switch(GTMENUITEM_USERDATA(menuitem)) {
  1330.                                  case MENU_CLOSE: closewindow=TRUE;
  1331.                                                   break;
  1332.                                  case MENU_QUIT:  Closing=TRUE;
  1333.                                                   break;
  1334.                                 }
  1335.  
  1336.                                 /* Get next menu event */
  1337.                                 menunum=menuitem->NextSelect;
  1338.                                }
  1339.                               }
  1340.                               break;
  1341.    case IDCMP_ACTIVEWINDOW:   if (!tmobj->do_Title) {
  1342.                                /* Borderless window */
  1343.                                struct RastPort *rp=tmobj->do_Window->RPort;
  1344.                                struct Gadget *g=&tmobj->do_DragGadget;
  1345.  
  1346.                                SetDrMd(rp,JAM1);
  1347.                                SetAPen(rp,tmobj->do_FillPen);
  1348.                                RectFill(rp,1,1,g->Width-2,g->Height-2);
  1349.                               }
  1350.                               break;
  1351.    case IDCMP_INACTIVEWINDOW: {
  1352.                                struct DockTool *dt=tmobj->do_Selected;
  1353.  
  1354.                                if (!tmobj->do_Title) {
  1355.                                 /* Borderless window */
  1356.                                 struct RastPort *rp=tmobj->do_Window->RPort;
  1357.                                 struct Gadget *g=&tmobj->do_DragGadget;
  1358.  
  1359.                                 SetDrMd(rp,JAM1);
  1360.                                 SetAPen(rp,tmobj->do_BackPen);
  1361.                                 RectFill(rp,1,1,g->Width-2,g->Height-2);
  1362.                                }
  1363.  
  1364.                                /* Missed a selectup??? */
  1365.                                if (dt) {
  1366.                                 struct TMLinkImage *tmli=dt->dt_ImageLink;
  1367.  
  1368.                                 /* Got non-ANIM image object? */
  1369.                                 if (tmli && !tmli->tmli_Link.tml_Active)
  1370.                                  CallActivateTMObject((struct TMLink *) tmli,
  1371.                                                       (void *) IOC_DEACTIVE);
  1372.  
  1373.                                 tmobj->do_Selected=NULL;
  1374.                                }
  1375.                               }
  1376.                               break;
  1377.   }
  1378.  
  1379.   /* Reply message */
  1380.   GT_ReplyIMsg(msg);
  1381.  
  1382.   /* Close window? */
  1383.   if (closewindow) CloseDockWindow(tmobj);
  1384.  }
  1385. }
  1386.